﻿using System;
using Microsoft.SharePoint;

namespace GDExtensions
{
    /// <summary>
    /// Extension methods for the <see cref="T:Microsoft.SharePoint.SPFolder"/> class.
    /// </summary>
    /// <remarks></remarks>
    public static class SPFolderExtensions
    {
        #region Public Methods
        /// <summary>
        /// Method to add a security group to a folder.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to add.</param>
        /// <param name="roleName">The name of the <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/>.</param>
        /// <remarks></remarks>
        public static void AddSecurityGroup(this SPFolder folder, SPGroup group, string roleName)
        {
            // Ensure the folder & group exist
            if (folder != null && group != null)
            {
                // Add the security group to the folder
                folder.AddSecurityGroup(group, folder.ParentWeb.GetRoleDefinitionByName(roleName));
            }
        }

        /// <summary>
        /// Method to add a security group to a folder.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to add.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPRoleType"/> role for the <paramref name="group"/>.</param>
        /// <remarks></remarks>
        public static void AddSecurityGroup(this SPFolder folder, SPGroup group, SPRoleType roleType)
        {
            // Ensure the folder & group exist
            if (folder != null && group != null)
            {
                // Add the security group to the folder
                folder.AddSecurityGroup(group, folder.ParentWeb.RoleDefinitions.GetByType(roleType));
            }
        }

        /// <summary>
        /// Method to add a security group to a folder
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to add.</param>
        /// <param name="roleDefinition">The <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/> role definition for the <paramref name="group"/>.</param>
        /// <remarks></remarks>
        public static void AddSecurityGroup(this SPFolder folder, SPGroup group, SPRoleDefinition roleDefinition)
        {
            // Call the private method
            _AddSecurityGroup(folder, group, roleDefinition);
        }

        /// <summary>
        /// Method to clear the folder permissions.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</param>
        /// <remarks></remarks>
        public static void ClearPermissions(this SPFolder folder)
        {
            // Call the private method
            _ClearPermissions(folder);
        }

        /// <summary>
        /// Method to create a sub folder.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> parent folder <paramref name="folder"/>.</param>
        /// <param name="folderName">The name of the <see cref="T:Microsoft.SharePoint.SPFolder"/> folder to create.</param>
        /// <returns>The <paramref name="folderName"/> <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</returns>
        /// <remarks></remarks>
        public static SPFolder CreateSubFolder(this SPFolder folder, string folderName)
        {
            // Call the private method
            return _CreateSubFolder(folder, folderName);
        }

        /// <summary>
        /// Method to find a sub-folder.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder to search in.</param>
        /// <param name="folderName">The name of the folder to find.</param>
        /// <returns>The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder if it exists, else NULL.</returns>
        public static SPFolder FindSubFolder(this SPFolder folder, string folderName)
        {
            // Find the sub-folder
            return folder.FindSubFolder(folderName, true);
        }

        /// <summary>
        /// Method to find a sub-folder.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder to search in.</param>
        /// <param name="folderName">The name of the folder to find.</param>
        /// <param name="recursiveFl">Flag to search the root folder recursively.</param>
        /// <returns>The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder if it exists, else NULL.</returns>
        public static SPFolder FindSubFolder(this SPFolder folder, string folderName, bool recursiveFl)
        {
            // Find the sub-folder
            return _FindSubFolder(folder, folderName, recursiveFl);
        }

        /// <summary>
        /// Method to remove a security group from a folder.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group to remove.</param>
        /// <remarks></remarks>
        public static void RemoveSecurityGroup(this SPFolder folder, string groupName)
        {
            // Remove the security group
            folder.RemoveSecurityGroup(folder.ParentWeb.GetSecurityGroup(groupName));
        }

        /// <summary>
        /// Method to remove a security group from a folder.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to remove.</param>
        public static void RemoveSecurityGroup(this SPFolder folder, SPGroup group)
        {
            // Call the private method
            _RemoveSecurityGroup(folder, group);
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Method to add a security group to a folder
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to add.</param>
        /// <param name="roleDefinition">The <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/> role definition for the <paramref name="group"/>.</param>
        /// <remarks></remarks>
        private static void _AddSecurityGroup(SPFolder folder, SPGroup group, SPRoleDefinition roleDefinition)
        {
            // Ensure the folder, group & role definition exist
            if (folder == null || !folder.Exists || group == null || roleDefinition == null)
            {
                return;
            }

            // Add the security group to the folder's list item
            folder.Item.AddSecurityGroup(group, roleDefinition);
        }

        /// <summary>
        /// Method to clear the folder permissions.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</param>
        /// <remarks></remarks>
        private static void _ClearPermissions(SPFolder folder)
        {
            // Ensure the folder exists
            if (folder == null || !folder.Exists) { return; }

            // Clear the folder's permissions
            folder.Item.ClearPermissions();
        }

        /// <summary>
        /// Method to create a sub folder.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> parent folder <paramref name="folder"/>.</param>
        /// <param name="folderName">The name of the <see cref="T:Microsoft.SharePoint.SPFolder"/> folder to create.</param>
        /// <returns>The <paramref name="folderName"/> <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</returns>
        /// <remarks></remarks>
        private static SPFolder _CreateSubFolder(SPFolder folder, string folderName)
        {
            // Create the sub folder
            return folder.DocumentLibrary.CreateFolder(folder.ServerRelativeUrl, folderName);
        }

        /// <summary>
        /// Method to find a sub-folder.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder to search in.</param>
        /// <param name="folderName">The name of the folder to find.</param>
        /// <param name="recursiveFl">Flag to search the root folder recursively.</param>
        /// <returns>The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder if it exists, else NULL.</returns>
        private static SPFolder _FindSubFolder(SPFolder folder, string folderName, bool recursiveFl)
        {
            // Parse the sub-folders
            foreach (SPFolder subFolder in folder.SubFolders)
            {
                // See if this if the sub-folder we are looking for
                if (subFolder.Name.Equals(folderName, StringComparison.CurrentCultureIgnoreCase))
                {
                    // Return the sub folder
                    return subFolder;
                }
            }

            // See if we are searching recursively
            if (recursiveFl)
            {
                // Parse the sub-folders
                foreach (SPFolder subFolder in folder.SubFolders)
                {
                    // Search the sub-folder
                    SPFolder folderToFind = subFolder.FindSubFolder(folderName, recursiveFl);

                    // See if the folder was found
                    if (folderToFind != null) { return folderToFind; }
                }
            }

            return default(SPFolder);
        }

        /// <summary>
        /// Method to remove a security group from a folder.
        /// </summary>
        /// <param name="folder">The <see cref="T:Microsoft.SharePoint.SPFolder"/> folder.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to remove.</param>
        private static void _RemoveSecurityGroup(SPFolder folder, SPGroup group)
        {
            // Remove the security group from the folder
            folder.Item.RemoveSecurityGroup(group);
        }
        #endregion
    }
}
